/**
 @file sys_at_mcu.c

 @author  Copyright (C) 2019 Centec Networks Inc.  All rights reserved.

 @date 2021-12-03

 @version v0.1

*/

/****************************************************************************
 *
 * Header Files
 *
 ****************************************************************************/
#include "sal.h"
#include "ctc_error.h"
#include "ctc_debug.h"
#include "ctc_interrupt.h"
#include "ctc_warmboot.h"
#include "drv_api.h"
#include "usw/include/drv_common.h"
#include "sys_usw_common.h"
#include "sys_usw_datapath.h"
#include "sys_usw_mac.h"
#include "sys_usw_eunit.h"
#include "sys_at_mcu.h"
#include "sys_at_datapath.h"
#include "sys_at_mcu_fw.inc"
#include "sys_usw_mcu.h"
#include "sys_usw_stats.h"

/****************************************************************************
 *
 * Defines and Macros
 *
 *****************************************************************************/
extern sal_file_t g_tm_dump_fp;
extern uint8 g_dmps_dbg_sw;
extern sys_datapath_master_t* p_usw_datapath_master[];

#define SYS_AT_MCU_ID_TO_CORE_ID(core_id, mcu_id)   (core_id = (mcu_id / AT_MCU_NUM_PER_CORE))
#define SYS_AT_MCU_ID_PER_CORE(mcu_id)   (mcu_id % AT_MCU_NUM_PER_CORE)
#define SYS_AT_CPUMAC_MCU_ID_CORE0  20
#define SYS_AT_CPUMAC_MCU_ID_CORE1  41
#define SYS_AT_IS_CPUMAC(mcu_id) (((mcu_id == SYS_AT_CPUMAC_MCU_ID_CORE0) || (mcu_id == SYS_AT_CPUMAC_MCU_ID_CORE1)) ? 1 : 0)
#define SYS_AT_MCUMEM_BYTES 16
#define SYS_AT_MCUMEM_WORDS 4
#define SYS_AT_MCU_STATS_RAM_TBL_ENTRY_NUM_PER_MCMAC 160
#define SYS_AT_MCU_STATS_RAM_TBL_ENTRY_NUM_PER_BLOCK 40

#ifdef DRV_IOW_FIELD
#undef DRV_IOW_FIELD
#define DRV_IOW_FIELD(lchip, memid, inst_id, fieldid, value, ptr) \
    do\
    {\
        int32 retv = 0;\
        char   fld_str[64] = {0};\
        retv = drv_set_field(lchip, memid, fieldid, ptr, value);\
        if (retv < 0)\
        {\
            return(retv); \
        }\
        drv_usw_get_field_string_by_id(lchip, memid, fieldid, fld_str);\
        if ((NULL != g_tm_dump_fp) && (g_dmps_dbg_sw))\
        {\
            sal_fprintf(g_tm_dump_fp, "write %-35s 0 inst %-5d field: %-45s 0x%x\n", \
                TABLE_NAME(lchip, memid), inst_id, fld_str, *value); \
        }\
    }\
    while(0)

#endif

/* DRV_IOW_FIELD extender, for index Not Zero */
#define DRV_IOW_FIELD_NZ(core_id, pp_id, dp_id, lchip, memid, inst_id, fieldid, value, ptr) \
    do\
    {\
        int32 retv = 0;\
        char   fld_str[64] = {0};\
        retv = drv_set_field(lchip, memid, fieldid, ptr, value);\
        if (retv < 0)\
        {\
            return(retv); \
        }\
        drv_usw_get_field_string_by_id(lchip, memid, fieldid, fld_str);\
        if ((NULL != g_tm_dump_fp) && (g_dmps_dbg_sw))\
        {\
            if ((255 != pp_id) && (255 != dp_id))\
            {\
                sal_fprintf(g_tm_dump_fp, "write %-35s 0 %-45s 0x%x inst %-5d core %u pp %u dp %u\n", \
                TABLE_NAME(lchip, memid), fld_str, *value, inst_id, core_id, pp_id, dp_id); \
            }\
            else if ((255 != pp_id))\
            {\
                sal_fprintf(g_tm_dump_fp, "write %-35s 0 %-45s 0x%x inst %-5d core %u pp %u\n", \
                TABLE_NAME(lchip, memid), fld_str, *value, inst_id, core_id, pp_id); \
            }\
            else\
            {\
                sal_fprintf(g_tm_dump_fp, "write %-35s 0 %-45s 0x%x inst %-5d core %u\n", \
                TABLE_NAME(lchip, memid), fld_str, *value, inst_id, core_id); \
            }\
        }\
    }\
    while(0)

#define DRV_IOW_ENTRY(lchip, memid, inst_id, entry_id, fieldid, value, ptr) \
    do\
    {\
        int32 retv = 0;\
        char   fld_str[64] = {0};\
        retv = drv_set_field(lchip, memid, fieldid, ptr, value);\
        if (retv < 0)\
        {\
            return(retv); \
        }\
        drv_usw_get_field_string_by_id(lchip, memid, fieldid, fld_str);\
        if ((NULL != g_tm_dump_fp) && (g_dmps_dbg_sw))\
        {\
            sal_fprintf(g_tm_dump_fp, "write %-35s %-5d %-45s 0x%x inst %-5d\n", \
                TABLE_NAME(lchip, memid), entry_id, fld_str, *value, inst_id); \
        }\
    }\
    while(0)

#define DRV_IOW_ENTRY_NZ(core_id, pp_id, dp_id, lchip, memid, inst_id, entry_id, fieldid, value, ptr) \
    do\
    {\
        int32 retv = 0;\
        char   fld_str[64] = {0};\
        retv = drv_set_field(lchip, memid, fieldid, ptr, value);\
        if (retv < 0)\
        {\
            return(retv); \
        }\
        drv_usw_get_field_string_by_id(lchip, memid, fieldid, fld_str);\
        if ((NULL != g_tm_dump_fp) && (g_dmps_dbg_sw))\
        {\
            if ((255 != pp_id) && (255 != dp_id))\
            {\
                sal_fprintf(g_tm_dump_fp, "write %-35s %-5d %-45s 0x%x inst %-5d core %u pp %u dp %u\n", \
                    TABLE_NAME(lchip, memid), entry_id, fld_str, *value, inst_id, core_id, pp_id, dp_id); \
            }\
            else if ((255 != pp_id))\
            {\
                sal_fprintf(g_tm_dump_fp, "write %-35s %-5d %-45s 0x%x inst %-5d core %u pp %u\n", \
                    TABLE_NAME(lchip, memid), entry_id, fld_str, *value, inst_id, core_id, pp_id); \
            }\
            else\
            {\
                sal_fprintf(g_tm_dump_fp, "write %-35s %-5d %-45s 0x%x inst %-5d core %u\n", \
                    TABLE_NAME(lchip, memid), entry_id, fld_str, *value, inst_id, core_id); \
            }\
        }\
    }\
    while(0)

#define DP_DEBUG_FUNCTION_CALLED_PRINT() \
    do \
    { \
        if ((NULL != g_tm_dump_fp) && (g_dmps_dbg_sw)) \
        {\
            sal_fprintf(g_tm_dump_fp, "------ %s enter ----------------\n", __func__); \
        }\
    } \
    while(0)

#define DP_DEBUG_FUNCTION_RETURN_PRINT() \
    do \
    { \
        if ((NULL != g_tm_dump_fp) && (g_dmps_dbg_sw)) \
        {\
            sal_fprintf(g_tm_dump_fp, "------ %s return ----------------\n", __func__); \
        }\
    } \
    while(0)


struct sys_at_mcu_dmps_msg_header_s
{
    uint32 type      :8;
    uint32 id        :8;
    uint32 data_len :16;
};
typedef struct sys_at_mcu_dmps_msg_header_s sys_at_mcu_dmps_msg_header_t;

struct sys_at_mcu_port_mapping_s
{
    uint32 dport        :16;
    uint32 psd_lane_bmp :8;
    uint32 if_mode      :5;
    uint32 an_fec       :3;
    uint32 ocs          :8;
    uint32 an_psd       :16;
    uint32 fec_type     :4;
    uint32 rsv          :4;
};
typedef struct sys_at_mcu_port_mapping_s sys_at_mcu_port_mapping_t;

uint8
_sys_at_mcu_check_mcu_is_used(uint8 lchip, uint8 mcu_id);


#define ____MCU_SYS_REG_IO____
int32
_sys_at_mcu_write_mcumem_drv(uint8 lchip, uint8 mcu_id, uint32 offset_addr, uint32 mask, uint32 value)
{
    uint32 core_id   = 0;
    uint32 cmd       = 0;
    uint32 inst_id   = SYS_AT_MCU_ID_PER_CORE(mcu_id);
    uint32 entry_id  = offset_addr / SYS_AT_MCUMEM_BYTES;
    uint32 index     = DRV_INS(inst_id, entry_id);
    uint32 m_mem[SYS_AT_MCUMEM_WORDS]  = {0x0};
    uint32 bit       = 0;
    uint32 raw_data  = 0;
    uint32 mask_op   = ~mask;

    SYS_CONDITION_RETURN(SYS_AT_MCU_NUM <= mcu_id, CTC_E_INVALID_CONFIG);
    sal_memset(m_mem, 0x0, sizeof(m_mem));
    
    /* Get Core ID */
    SYS_AT_MCU_ID_TO_CORE_ID(core_id, mcu_id);

    /* read total entry */
    cmd = DRV_IOR(McuMem_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DMPS_DRV_IOCTL_CORE(lchip, index, core_id, cmd, m_mem));

    /* Modified value */
    if(0x0 != mask)
    {
        for(bit = 0; 0 == ((mask_op >> bit) & 0x1); bit++);
        
        value = value << bit;
        raw_data = m_mem[(offset_addr % SYS_AT_MCUMEM_BYTES) / SYS_AT_MCUMEM_WORDS];
        value |= (raw_data & mask);
    }
    
    m_mem[(offset_addr % SYS_AT_MCUMEM_BYTES) / SYS_AT_MCUMEM_WORDS] = value;

    cmd = DRV_IOW(McuMem_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DMPS_DRV_IOCTL_CORE(lchip, index, core_id, cmd, m_mem));

    return CTC_E_NONE;
}

int32
_sys_at_mcu_read_mcumem_drv(uint8 lchip, uint8 mcu_id, uint32 offset_addr, uint32 mask, uint32 *value)
{
    uint32 core_id   = 0;
    uint32 cmd       = 0;
    uint32 inst_id   = SYS_AT_MCU_ID_PER_CORE(mcu_id);
    uint32 entry_id  = offset_addr / SYS_AT_MCUMEM_BYTES;
    uint32 index     = DRV_INS(inst_id, entry_id);
    uint32 m_mem[SYS_AT_MCUMEM_WORDS]  = {0x0};
    uint32 bit       = 0;
    uint32 raw_data  = 0;
    uint32 mask_op   = ~mask;

    SYS_CONDITION_RETURN(SYS_AT_MCU_NUM <= mcu_id, CTC_E_INVALID_CONFIG);
    sal_memset(m_mem, 0x0, sizeof(m_mem));
    
    /* Get Core ID */
    SYS_AT_MCU_ID_TO_CORE_ID(core_id, mcu_id);

    /* read total entry */
    cmd = DRV_IOR(McuMem_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DMPS_DRV_IOCTL_CORE(lchip, index, core_id, cmd, m_mem));

    raw_data = m_mem[(offset_addr % SYS_AT_MCUMEM_BYTES) / SYS_AT_MCUMEM_WORDS];

    raw_data &= mask_op;
    for(bit = 0; 0 == ((mask_op >> bit) & 0x1); bit++);
    *value = raw_data >> bit;

    return CTC_E_NONE;
}

int32
sys_at_mcu_read_shared_memory(uint8 lchip, uint8 mcu_id, uint32 addr, uint32 mask, uint32 *value)
{
    CTC_PTR_VALID_CHECK(value);

    if ((SYS_AT_MCU_NUM <= mcu_id) || (addr > SYS_AT_MCU_SHARED_MEM_SIZE))
    {
        return CTC_E_INVALID_PARAM;
    }

    CTC_ERROR_RETURN(_sys_at_mcu_read_mcumem_drv(lchip, mcu_id, addr + SYS_AT_MCU_SHARED_MEM_OFFSET_ADDR, mask, value));

    return CTC_E_NONE;
}

int32
sys_at_mcu_write_shared_memory(uint8 lchip, uint8 mcu_id, uint32 addr, uint32 mask, uint32 value)
{
    if ((SYS_AT_MCU_NUM <= mcu_id) || (addr > SYS_AT_MCU_SHARED_MEM_SIZE))
    {
        return CTC_E_INVALID_PARAM;
    }

    CTC_ERROR_RETURN(_sys_at_mcu_write_mcumem_drv(lchip, mcu_id, addr + SYS_AT_MCU_SHARED_MEM_OFFSET_ADDR, mask, value));

    return CTC_E_NONE;
}

int32 sys_at_mcu_reset_core(uint8 lchip, uint32 mcu_id, uint8 reset)
{   
    uint32 core_id   = 0;
    uint32 inst_id   = 0;
    uint32 index     = 0;
    uint32 cmd       = 0;
    uint32 value     = 0;
    uint32 tbl_id    = 0;
    uint32 field_id  = 0;
    CtcMacCtlReset_m   CtcMacCtlReset;
    CtcMiscCtlReset_m  CtcMiscCtlReset;

    value = reset ? 1 : 0;

    /* Get Core ID */
    SYS_AT_MCU_ID_TO_CORE_ID(core_id, mcu_id);
    
    if (SYS_AT_IS_CPUMAC(mcu_id))
    {
        tbl_id    = CtcMiscCtlReset_t;
        field_id  = CtcMiscCtlReset_resetCoreMcu_f;
        index = DRV_INS(inst_id, 0);
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DMPS_DRV_IOCTL_CORE(lchip, index, core_id, cmd, &CtcMiscCtlReset)); 

        DRV_IOW_FIELD_NZ(core_id, 0xff, 0xff, lchip, tbl_id, mcu_id, field_id, &value, &CtcMiscCtlReset);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DMPS_DRV_IOCTL_CORE(lchip, index, core_id, cmd, &CtcMiscCtlReset));
    }
    else
    {
        tbl_id    = CtcMacCtlReset_t;
        field_id  = CtcMacCtlReset_resetCoreMcu_f;
        inst_id   = SYS_AT_MCU_ID_PER_CORE(mcu_id);
        index = DRV_INS(inst_id, 0);
        cmd = DRV_IOR(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DMPS_DRV_IOCTL_CORE(lchip, index, core_id, cmd, &CtcMacCtlReset)); 

        DRV_IOW_FIELD_NZ(core_id, 0xff, 0xff, lchip, tbl_id, mcu_id, field_id, &value, &CtcMacCtlReset);
        cmd = DRV_IOW(tbl_id, DRV_ENTRY_FLAG);
        CTC_ERROR_RETURN(DMPS_DRV_IOCTL_CORE(lchip, index, core_id, cmd, &CtcMacCtlReset));
    }

    return CTC_E_NONE;
}

int32
sys_at_mcu_set_msg_header_field(void *p_header, uint8 field, uint32 val)
{
    sys_at_mcu_dmps_msg_header_t* p_tmp_header = (sys_at_mcu_dmps_msg_header_t*)p_header;

    switch(field)
    {
        case SYS_DMPS_MSG_HEADER_TYPE:
            p_tmp_header->type = val;
            break;
        case SYS_DMPS_MSG_HEADER_ID:
            p_tmp_header->id = val;
            break;
        case SYS_DMPS_MSG_HEADER_DATA_LEN:
            p_tmp_header->data_len = val;
            break;
        default:
            return CTC_E_NOT_SUPPORT;
    }
    
    return CTC_E_NONE;
}

int32
sys_at_mcu_get_msg_header_field(void *p_header, uint8 field, uint32* p_val)
{
    sys_at_mcu_dmps_msg_header_t* p_tmp_header = (sys_at_mcu_dmps_msg_header_t*)p_header;

    switch(field)
    {
        case SYS_DMPS_MSG_HEADER_TYPE:
            *p_val = p_tmp_header->type;
            break;
        case SYS_DMPS_MSG_HEADER_ID:
            *p_val = p_tmp_header->id;
            break;
        case SYS_DMPS_MSG_HEADER_DATA_LEN:
            *p_val = p_tmp_header->data_len;
            break;
        default:
            *p_val = 0xFFFF;
            break;
    }
    
    return CTC_E_NONE;
}

int32 
sys_at_mcu_gen_c2m_intr(uint8 lchip, uint8 mcu_id)
{
    uint32 core_id       = 0;
    uint32 cmd           = 0;
    uint32 m_intr_ctl[4] = {0x0};
    uint32 inst_id       = SYS_AT_MCU_ID_PER_CORE(mcu_id);
    uint32 entry_id      = 0;
    uint32 index         = DRV_INS(inst_id, entry_id);

    /* Get Core ID */
    SYS_AT_MCU_ID_TO_CORE_ID(core_id, mcu_id);

    /* Read */
    cmd = DRV_IOR(McpuIntrExtCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DMPS_DRV_IOCTL_CORE(lchip, index, core_id, cmd, m_intr_ctl));
    
    /* Modified */
    m_intr_ctl[0] |= 0x1;

    /* Write */
    cmd = DRV_IOW(McpuIntrExtCtl_t, DRV_ENTRY_FLAG);
    CTC_ERROR_RETURN(DMPS_DRV_IOCTL_CORE(lchip, index, core_id, cmd, m_intr_ctl));

    return CTC_E_NONE;
}

#define ____MCU_SYS_LOAD_IMAGE____

int32
_sys_at_mcu_load_fw(uint8 lchip, uint8 mcu_id)
{
    uint32 core_id   = 0;
    uint32 index     = 0;
    uint32 inst_id   = SYS_AT_MCU_ID_PER_CORE(mcu_id);
    uint32 entry_id  = 0;
    uint32 entry_num = 0;
    uint32 len       = sizeof(g_at_mcu_fw) / sizeof(uint32);
    uint32 cmd       = DRV_IOW(McuMem_t, DRV_ENTRY_FLAG);

    SYS_CONDITION_RETURN(SYS_AT_MCU_NUM <= mcu_id, CTC_E_INVALID_CONFIG);
 
    /* Get Core ID */
    SYS_AT_MCU_ID_TO_CORE_ID(core_id, mcu_id);

    entry_num = len / SYS_AT_MCUMEM_WORDS;
    for(entry_id = 0; entry_id < entry_num; entry_id ++)
    {
        index = DRV_INS(inst_id, entry_id);
        CTC_ERROR_RETURN(DMPS_DRV_IOCTL_CORE(lchip, index, core_id, cmd, g_at_mcu_fw + entry_id*SYS_AT_MCUMEM_WORDS));        
    }
    
    return CTC_E_NONE;
}

int32
sys_at_mcu_load_image(uint8 lchip, uint32 mcu_id)
{
    CTC_ERROR_RETURN(_sys_at_mcu_load_fw(lchip, mcu_id));
    
    return CTC_E_NONE;
}

static int32
_sys_at_mcu_msg_recv_cb_dump_db(uint8 lchip, uint8 mcu_id, uint32 msg_id, void *p_in_data, void *p_out)
{
    uint8 idx      = 0;
    uint32 addr    = 0;
    uint32 idx_u32 = 0;
    uint32* p_val32 = NULL;
    sys_at_mcu_port_mapping_t port_mapping;
    dmps_msg_ds_dump_mcu_db_t* p_data = (dmps_msg_ds_dump_mcu_db_t*)p_in_data;

    if (NULL == p_data)
    {
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_ERROR, " %% Sync Response Msg Data is NULL. | %s()@%d\n", __FUNCTION__, __LINE__);
        return CTC_E_INVALID_PTR;
    }
    
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"[MCU DB]\n");
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    %-24s : %d\n", "mcu_id", p_data->mcu_id);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    %-24s : %d\n", "anlt_sm_timeout", p_data->anlt_sm_timeout);

    p_val32 = (uint32*)&port_mapping;
    for (idx = 0; idx < 8; idx ++)
    {

        addr    = MCU_GLB_INFO_PORT_MAPPING_BASE + idx * sizeof(sys_at_mcu_port_mapping_t);
        for (idx_u32 = 0; idx_u32 < sizeof(sys_at_mcu_port_mapping_t) / sizeof(uint32); idx_u32 ++)
        {
            CTC_ERROR_RETURN(sys_at_mcu_read_shared_memory(lchip, mcu_id, addr, 0x0, p_val32 + idx_u32));
            addr += sizeof(uint32);
        }
    
        if (0xffff == port_mapping.dport)
        {
            continue;
        }
        
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    ***************************************\n");
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    %-24s : %d\n",     "ANLT-SM state",         p_data->anlt_sm[idx].state);
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    %-24s : %d\n",     "ANLT-SM anlt_en",       p_data->anlt_sm[idx].anlt_en);
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    %-24s : %d\n",     "ANLT-SM timer_type",    p_data->anlt_sm[idx].timer_type);
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    %-24s : 0x%x\n",   "ANLT-SM lt_done_bmp",   p_data->anlt_sm[idx].lt_done_bmp);
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    %-24s : %d\n",     "ANLT-SM Timer_en",      p_data->anlt_sm[idx].timer_en);
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    %-24s : %d\n",     "ANLT-SM upd_timer_cnt", p_data->anlt_sm[idx].parameter);

        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    %-24s : %d\n",     "PORT-MAPPING dport",        port_mapping.dport);
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    %-24s : 0x%02x\n", "PORT-MAPPING psd_lane_bmp", port_mapping.psd_lane_bmp);
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    %-24s : 0x%02x\n", "PORT-MAPPING if_mode",      port_mapping.if_mode);
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    %-24s : 0x%02x\n", "PORT-MAPPING an_fec",       port_mapping.an_fec);
        SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP,"    %-24s : 0x%02x\n", "PORT-MAPPING an_psd",       port_mapping.an_psd);
    }
    
    return CTC_E_NONE;
}


int32
sys_at_mcu_dump_db_info(uint8 lchip, uint8 mcu_id)
{   
    /* Send Message to MCU */
    CTC_ERROR_RETURN(sys_usw_dmps_msg_sync_send(lchip, mcu_id, SYS_DMPS_MSG_CODE_SYNC_C2M_DUMP_DB, 0x0, NULL, NULL)); 

    return CTC_E_NONE;
}

static int32
_sys_at_mcu_msg_recv_cb_get_anlt_state(uint8 lchip, uint8 mcu_id, uint32 msg_id, void *p_in_data, void *p_out)
{
    uint32* p_data   = (uint32*)p_in_data;
    uint32* p_data_out = (uint32*)p_out;

    CTC_PTR_VALID_CHECK(p_in_data);
    CTC_PTR_VALID_CHECK(p_out);

    *p_data_out = *p_data;

    return CTC_E_NONE;
}

int32
sys_at_mcu_get_anlt_state(uint8 lchip, uint16 dport, uint32* p_state)
{   
    uint8  mcu_id       = 0;
    uint32 first_lsd    = 0;
    sys_dmps_db_upt_info_t port_info    = {0};

    if (NULL == MCHIP_DMPS(lchip)->anlt_sm_get_mcu_id_by_dport)
    {
        return CTC_E_NOT_SUPPORT;
    } 
    CTC_ERROR_RETURN(MCHIP_DMPS(lchip)->anlt_sm_get_mcu_id_by_dport(lchip, dport, &mcu_id));

    CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
    DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_DPORT, dport);
    CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &port_info));
    DMPS_DB_GET_MAP_INFO(port_info, DMPS_DB_LOGIC_SERDES,   first_lsd);

    if(!_sys_at_mcu_check_mcu_is_used(lchip, mcu_id))
    {
        return CTC_E_NONE;
    }
    
    /* Send Message to MCU */
    CTC_ERROR_RETURN(sys_usw_dmps_msg_sync_send(lchip, mcu_id, SYS_DMPS_MSG_CODE_SYNC_C2M_GET_ANLT_STATE, sizeof(uint32), &first_lsd, p_state)); 

    return CTC_E_NONE;
}

int32
sys_at_mcu_send_link_up_intr(uint8 lchip, uint16 dport)
{   
    uint8  mcu_id       = 0;
    dmps_msg_ds_anlt_sm_en_t send_data  = {0x0};
    sys_dmps_db_upt_info_t port_info    = {0};

    if (NULL == MCHIP_DMPS(lchip)->anlt_sm_get_mcu_id_by_dport)
    {
        return CTC_E_NOT_SUPPORT;
    } 
    CTC_ERROR_RETURN(MCHIP_DMPS(lchip)->anlt_sm_get_mcu_id_by_dport(lchip, dport, &mcu_id));

    CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
    DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_DPORT, dport);
    CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &port_info));
    DMPS_DB_GET_MAP_INFO(port_info, DMPS_DB_LOGIC_SERDES,   send_data.first_lsd);
    
    /* Send Message to MCU */
    CTC_ERROR_RETURN(sys_usw_dmps_msg_sync_send(lchip, mcu_id, SYS_DMPS_MSG_CODE_SYNC_C2M_LINK_UP_INTR, sizeof(dmps_msg_ds_anlt_sm_en_t), &send_data, NULL)); 

    return CTC_E_NONE;
}

int32
sys_at_mcu_send_link_adjust_intr(uint8 lchip, uint16 dport)
{   
    uint8  mcu_id       = 0;
    dmps_msg_ds_anlt_sm_en_t send_data  = {0x0};
    sys_dmps_db_upt_info_t port_info    = {0};

    if (NULL == MCHIP_DMPS(lchip)->anlt_sm_get_mcu_id_by_dport)
    {
        return CTC_E_NOT_SUPPORT;
    } 
    CTC_ERROR_RETURN(MCHIP_DMPS(lchip)->anlt_sm_get_mcu_id_by_dport(lchip, dport, &mcu_id));

    CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
    DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_DPORT, dport);
    CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &port_info));
    DMPS_DB_GET_MAP_INFO(port_info, DMPS_DB_LOGIC_SERDES,   send_data.first_lsd);
    
    /* Send Message to MCU */
    CTC_ERROR_RETURN(sys_usw_dmps_msg_sync_send(lchip, mcu_id, SYS_DMPS_MSG_CODE_SYNC_C2M_LINK_ADJUST, sizeof(dmps_msg_ds_anlt_sm_en_t), &send_data, NULL)); 

    return CTC_E_NONE;
}

int32
sys_at_mcu_dmps_msg_cb_register(uint8 lchip)
{      
    /* init register_tab */
    DMPS_MSG_REGISTER_RX_CB_NZ(lchip, SYS_DMPS_MSG_CODE_SYNC_C2M_DUMP_DB, sizeof(dmps_msg_ds_dump_mcu_db_t), _sys_at_mcu_msg_recv_cb_dump_db);
    DMPS_MSG_REGISTER_RX_CB_NZ(lchip, SYS_DMPS_MSG_CODE_SYNC_C2M_GET_ANLT_STATE, sizeof(uint32), _sys_at_mcu_msg_recv_cb_get_anlt_state);
   
    CTC_ERROR_RETURN(sys_usw_dmps_anlt_sm_register_msg(lchip));

    return CTC_E_NONE;
}

int32
_sys_at_mcu_get_mcu_use_info(uint8 lchip, sys_dmps_db_msg_mcu_info_t* p_mcu_info)
{
    uint8  core_num     = (SYS_AT_CHIP_IS_DC(lchip)) ? 2 : 1;
#ifndef EMULATION_ENV
    uint8  core_id      = 0;
    uint8  mac_group_id = 0;
    uint8  mcu_id       = 0;
    uint32 mac_group_valid = 0;
//- uint8  power_down   = FALSE;
#endif
    uint32 use_mcu_num  = 0;

    sal_memset(p_mcu_info, 0x0, sizeof(sys_dmps_db_msg_mcu_info_t));

#ifdef EMULATION_ENV
        uint8 chip_type = SYS_AT_GET_CHIP_TYPE(lchip);
        if (SYS_AT_IS_1PP(chip_type))
        {
            CTC_BMP_SET(p_mcu_info->mcu_bmp, 16);
            CTC_BMP_SET(p_mcu_info->mcu_bmp, 17);
            use_mcu_num = 2;
        }
#else
    for (core_id = 0; core_id < core_num; core_id ++)
    {
        CTC_ERROR_RETURN(sys_usw_dmps_db_get_mac_group_valid(lchip, core_id, &mac_group_valid));
        for (mac_group_id = 0; mac_group_id < AT_MCMAC_NUM_PER_CORE; mac_group_id++)
        {
            if(CTC_IS_BIT_SET(mac_group_valid, mac_group_id))
            {
                mcu_id = core_id*AT_MCU_NUM_PER_CORE + mac_group_id;

                //- if (power_down)
                //-{
                //-    continue;    
                //-}
                
                CTC_BMP_SET(p_mcu_info->mcu_bmp, mcu_id);
                use_mcu_num ++;
            }
        }

        /* CPUMAC */
        mcu_id = core_id*AT_MCU_NUM_PER_CORE + (AT_MCU_NUM_PER_CORE - 1); 
        CTC_BMP_SET(p_mcu_info->mcu_bmp, mcu_id);
        use_mcu_num ++;
    }
#endif 
 
    p_mcu_info->max_mcu_num = core_num * AT_MCU_NUM_PER_CORE;
    p_mcu_info->use_mcu_num = use_mcu_num;
    p_mcu_info->core_mcu_num = AT_MCU_NUM_PER_CORE;

    return CTC_E_NONE;
}

uint8
_sys_at_mcu_check_mcu_is_used(uint8 lchip, uint8 mcu_id)
{
    uint8 is_used                        = FALSE;
    sys_dmps_db_msg_mcu_info_t mcu_info = {0x0};

    CTC_ERROR_RETURN(_sys_at_mcu_get_mcu_use_info(lchip, &mcu_info));

    if (CTC_BMP_ISSET(mcu_info.mcu_bmp, mcu_id))
    {
        is_used = TRUE;
    }
    
    return is_used;
}

int32
_sys_at_mcu_init_port_mapping_mem(uint8 lchip, uint8 mcu_id)
{   
    uint8  idx    = 0;
    uint32 addr   = 0;

    for (idx = 0; idx < AT_SERDES_NUM_PER_MCMAC; idx ++)
    {
        addr = MCU_GLB_INFO_PORT_MAPPING_BASE + idx * sizeof(sys_at_mcu_port_mapping_t);
        CTC_ERROR_RETURN(sys_at_mcu_write_shared_memory(lchip, mcu_id, addr, 0x0, 0xffffffff));
    }
    
    return CTC_E_NONE;
}

int32
sys_at_mcu_init(uint8 lchip)
{
    uint8  mcu_id    = 0;
    uint16 dport     = 0;
    /* 
     * +------------------------------+ 0 K
     * +          Glb Info            +
     * +------------------------------+ 2 K
     * +          Mac Stats           +
     * +------------------------------+ 7 K  
     * +          Log Info            +
     * +------------------------------+ 12 K
     * +          Sync Buf            +
     * +------------------------------+ 13 K
     * +          ASync Buf           + 
     * +------------------------------+ c K
     */
    sys_dmps_db_msg_init_info_t init_info = 
    {
        /* header_len         */ sizeof(sys_at_mcu_dmps_msg_header_t),
        /* priority_num       */ 2,
        /* msg_id_num         */ 256,
        /* buf_addr           */ 1024*12,
        /* sync_buf_len       */ 1024,
        /* async_buf_len      */ 512,
        /* log_len            */ 1024*5,
        /* log_addr           */ 1024*7,
        /* read               */ sys_at_mcu_read_shared_memory,
        /* write              */ sys_at_mcu_write_shared_memory,
        /* gen_intr           */ sys_at_mcu_gen_c2m_intr,
        /* get_header_field   */ sys_at_mcu_get_msg_header_field, 
        /* set_header_field   */ sys_at_mcu_set_msg_header_field,
    };

#if(1 == SDK_WORK_PLATFORM)
        return CTC_E_NONE;
#endif

    CTC_ERROR_RETURN(_sys_at_mcu_get_mcu_use_info(lchip, &init_info.mcu_info));
    /* load mcu image */
    for(mcu_id = 0; mcu_id < init_info.mcu_info.max_mcu_num; mcu_id ++)
    {
        if (!CTC_BMP_ISSET(init_info.mcu_info.mcu_bmp, mcu_id))
        {
            continue;
        }
        
        CTC_ERROR_RETURN(sys_at_mcu_load_image(lchip, mcu_id));
#ifdef EMULATION_ENV
        CTC_ERROR_RETURN(sys_at_mcu_write_shared_memory(lchip, mcu_id, MCU_GLB_INFO_ANLT_SM_AN_TIMEOUT,      0x0, 6));
        CTC_ERROR_RETURN(sys_at_mcu_write_shared_memory(lchip, mcu_id, MCU_GLB_INFO_ANLT_SM_LT_TIMEOUT,      0x0, 3));
        CTC_ERROR_RETURN(sys_at_mcu_write_shared_memory(lchip, mcu_id, MCU_GLB_INFO_ANLT_SM_LINK_UP_TIMEOUT, 0x0, 10));
#else
        /* init anlt SM timeout : 300 OS Tick = 300 * 10ms = 3s*/
        CTC_ERROR_RETURN(sys_at_mcu_write_shared_memory(lchip, mcu_id, MCU_GLB_INFO_ANLT_SM_AN_TIMEOUT,      0x0, 3000));
        CTC_ERROR_RETURN(sys_at_mcu_write_shared_memory(lchip, mcu_id, MCU_GLB_INFO_ANLT_SM_LT_TIMEOUT,      0x0, 300));
        CTC_ERROR_RETURN(sys_at_mcu_write_shared_memory(lchip, mcu_id, MCU_GLB_INFO_ANLT_SM_LINK_UP_TIMEOUT, 0x0, 1500));
#endif
        CTC_ERROR_RETURN(sys_at_mcu_write_shared_memory(lchip, mcu_id, MCU_GLB_INFO_LINK_ADJUST_EN,          0x0, 0));
        /* init mcu port mapping */
        CTC_ERROR_RETURN(_sys_at_mcu_init_port_mapping_mem(lchip, mcu_id));
    }

    /* init dmps msg */
    CTC_ERROR_RETURN(sys_usw_dmps_msg_init(lchip, &init_info));

    /* init register_tab */
    CTC_ERROR_RETURN(sys_at_mcu_dmps_msg_cb_register(lchip));
    for (dport = 0; dport < DMPS_MAX_PORT_NUM; dport ++)
    {
        if (!sys_usw_dmps_db_is_valid_id(lchip, DMPS_DB_TYPE_PORT, dport))
        {
            continue;
        }
        (void)sys_at_mcu_add_port_mapping(lchip, dport);
    }

    /* run mcu */
    for(mcu_id = 0; mcu_id < init_info.mcu_info.max_mcu_num; mcu_id ++)
    {
        if (!CTC_BMP_ISSET(init_info.mcu_info.mcu_bmp, mcu_id))
        {
            continue;
        }
        CTC_ERROR_RETURN(sys_at_mcu_reset_core(lchip, mcu_id, 0));
    }

    return CTC_E_NONE;
}

int32
sys_at_mcu_del_port_mapping(uint8 lchip, uint16 dport)
{   
    uint8  core_id      = 0;
    uint8  mcu_id       = 0;
    uint32 first_lsd    = 0;
    uint32 addr         = 0;
    sys_dmps_db_upt_info_t port_info    = {0};

    if (NULL == MCHIP_DMPS(lchip)->anlt_sm_get_mcu_id_by_dport)
    {
        return CTC_E_NOT_SUPPORT;
    } 
    CTC_ERROR_RETURN(MCHIP_DMPS(lchip)->anlt_sm_get_mcu_id_by_dport(lchip, dport, &mcu_id));

    CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
    DMPS_DB_SET_MAP_INFO(port_info, DMPS_DB_DPORT, dport);
    CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &port_info));
    DMPS_DB_GET_MAP_INFO(port_info, DMPS_DB_LOGIC_SERDES,   first_lsd);

    addr   = MCU_GLB_INFO_PORT_MAPPING_BASE + (first_lsd % AT_SERDES_NUM_PER_MCMAC) * sizeof(sys_at_mcu_port_mapping_t);
    if(!_sys_at_mcu_check_mcu_is_used(lchip, mcu_id))
    {
        return CTC_E_NONE;
    }

    SYS_AT_MCU_ID_TO_CORE_ID(core_id, mcu_id);
    PORT_MAPPING_HW_LOCK(lchip, core_id, SYS_AT_MCU_ID_PER_CORE(mcu_id));
    CTC_ERROR_DUMP(sys_at_mcu_write_shared_memory(lchip, mcu_id, addr, 0x0, 0xffffffff));
    PORT_MAPPING_HW_UNLOCK(lchip, core_id, SYS_AT_MCU_ID_PER_CORE(mcu_id));

    return CTC_E_NONE;
}

int32
sys_at_mcu_add_port_mapping(uint8 lchip, uint16 dport)
{   
    uint8  core_id    = 0;
    uint8  mcu_id     = 0;
    uint8  serdes_num = 0;
    uint8  port_type  = 0;
    uint8  if_mode    = 0;
    uint32 first_lsd  = 0;
    uint32 addr       = 0;
    uint32 idx        = 0x0;
    uint32 *p_val32   = NULL;
    uint16 psd[DMPS_MAX_NUM_PER_MODULE] = {0};
    sys_at_mcu_port_mapping_t port_mapping;
    sys_dmps_db_upt_info_t port_info = {0};

    if (NULL == MCHIP_DMPS(lchip)->anlt_sm_get_mcu_id_by_dport)
    {
        return CTC_E_NOT_SUPPORT;
    } 
    CTC_ERROR_RETURN(MCHIP_DMPS(lchip)->anlt_sm_get_mcu_id_by_dport(lchip, dport, &mcu_id));

    sal_memset(&port_mapping, 0x0, sizeof(sys_at_mcu_port_mapping_t));

    /*init cfg */
    port_mapping.an_fec = (1 << CTC_PORT_FEC_TYPE_RS) | (1 << CTC_PORT_FEC_TYPE_BASER);

    /*mapping info */
    CTC_ERROR_RETURN(sys_usw_dmps_db_get_relative_id(lchip, DMPS_DB_TYPE_PORT, dport, DMPS_DB_TYPE_PSD, &serdes_num, psd));

    CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
    DMPS_DB_SET_MAP_INFO(port_info,      DMPS_DB_DPORT, dport);
    DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PORT_IF_MODE);
    DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PORT_TYPE);
    DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PORT_AN_FEC);
    DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PSD_OCS);
    DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PORT_FEC_TYPE);
    CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &port_info));
    DMPS_DB_GET_MAP_INFO(port_info, DMPS_DB_LOGIC_SERDES,   first_lsd);
    DMPS_DB_GET_MAP_INFO(port_info, DMPS_DB_PHYSIC_SERDES,   port_mapping.an_psd);
    DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PORT_IF_MODE, if_mode);
    DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PORT_AN_FEC,  port_mapping.an_fec);
    DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PORT_TYPE,    port_type);
    DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PSD_OCS,      port_mapping.ocs);
    DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PORT_FEC_TYPE,port_mapping.fec_type);

    if (!SYS_USW_IS_NETWORK_PORT(port_type))
    {
        return CTC_E_NONE;
    }
   
    port_mapping.dport        = dport;
    port_mapping.psd_lane_bmp = 0x0;
    CTC_SERDES_MODE_TO_SYS_MCU_SERDES_MODE(if_mode, port_mapping.if_mode);
    for (idx = 0; idx < serdes_num; idx ++ )
    {
        CTC_BIT_SET(port_mapping.psd_lane_bmp, psd[idx] % AT_SERDES_NUM_PER_MCMAC);
    }
  
    idx       = first_lsd % AT_SERDES_NUM_PER_MCMAC;
    addr      = MCU_GLB_INFO_PORT_MAPPING_BASE + (first_lsd % AT_SERDES_NUM_PER_MCMAC) * sizeof(sys_at_mcu_port_mapping_t);

    p_val32 = (uint32*)&port_mapping;
    if(!_sys_at_mcu_check_mcu_is_used(lchip, mcu_id))
    {
        return CTC_E_NONE;
    }

    SYS_AT_MCU_ID_TO_CORE_ID(core_id, mcu_id);
    PORT_MAPPING_HW_LOCK(lchip, core_id, SYS_AT_MCU_ID_PER_CORE(mcu_id));
    for (idx = 0; idx < sizeof(sys_at_mcu_port_mapping_t) / sizeof(uint32); idx ++)
    {
        CTC_ERROR_DUMP(sys_at_mcu_write_shared_memory(lchip, mcu_id, addr, 0x0, p_val32[idx]));
        addr += sizeof(uint32);
    }
    PORT_MAPPING_HW_UNLOCK(lchip, core_id, SYS_AT_MCU_ID_PER_CORE(mcu_id));

    return CTC_E_NONE;
}

int32
_sys_at_mcu_read_mac_stats(uint8 lchip, uint8 core_id, uint8 mcu_id, uint8 block_id, sys_usw_dmps_mac_stats_t* p_mac_stats)
{   
    uint32 idx         = 0;
    uint32 inst_id     = SYS_AT_MCU_ID_PER_CORE(mcu_id);
    uint32 entry_id    = 0;
    uint32 cmd         = 0;
    uint32 index       = 0;
    uint32 base_addr   = SYS_AT_MCU_SHARED_MEM_OFFSET_ADDR + MCU_GLB_INFO_MAC_STATS_BASE_ADDR + block_id * sizeof(sys_usw_dmps_mac_stats_t);
    uint32* p_val_u32    = (uint32*)p_mac_stats;

    if(!_sys_at_mcu_check_mcu_is_used(lchip, mcu_id))
    {
        return CTC_E_NONE;
    }

    cmd = DRV_IOR(McuMem_t, DRV_ENTRY_FLAG);
    entry_id = base_addr / SYS_AT_MCUMEM_BYTES;
    for (idx = 0; idx < sizeof(sys_usw_dmps_mac_stats_t) / SYS_AT_MCUMEM_BYTES; idx ++)
    {
        index       = DRV_INS(inst_id, entry_id);
        CTC_ERROR_RETURN(DMPS_DRV_IOCTL_CORE(lchip, index, core_id, cmd, p_val_u32));
        entry_id ++;
        p_val_u32 += SYS_AT_MCUMEM_WORDS;
    }

    return CTC_E_NONE;
}

int32
sys_at_mcu_get_mac_stats(uint8 lchip, uint32 block_id, sys_usw_dmps_mac_stats_t* p_mac_stats)
{   
    struct data_struct_s
    {
        uint32 stas_block_id  :8;
        uint32 resv           :24;
    };
    typedef struct data_struct_s data_struct_t; 
    uint16 start_idx        = block_id & 0xffff;
    uint8 ram_id            = (block_id >> 16) & 0x3;
    uint8 core_id           = (block_id >> 18) & 0x1;
    uint8 mcu_id            = 0;
    uint8 block_base_id     = 0;
    uint8 mac_group_id      = 0;
    data_struct_t send_data = {0x0};

    mac_group_id = start_idx / SYS_AT_MCU_STATS_RAM_TBL_ENTRY_NUM_PER_MCMAC;    
    mcu_id  = core_id*AT_MCU_NUM_PER_CORE + ((ram_id == 2) ? (AT_MCU_NUM_PER_CORE - 1) : mac_group_id);
    block_base_id = (ram_id == 1) ? 4 : 0;

    /* Send Sync Msg */
    send_data.stas_block_id = block_base_id + (start_idx % SYS_AT_MCU_STATS_RAM_TBL_ENTRY_NUM_PER_MCMAC) / SYS_AT_MCU_STATS_RAM_TBL_ENTRY_NUM_PER_BLOCK;
    CTC_ERROR_RETURN(sys_usw_dmps_msg_sync_send(lchip, mcu_id, SYS_DMPS_MSG_CODE_SYNC_C2M_GET_MAC_STATS, sizeof(data_struct_t), &send_data, NULL)); 
    
    /* read mac stats */
    CTC_ERROR_RETURN(_sys_at_mcu_read_mac_stats(lchip, core_id, mcu_id, send_data.stas_block_id, p_mac_stats));

    return CTC_E_NONE;
}

int32
sys_at_mcu_clear_mac_stats(uint8 lchip, uint32 block_id, uint8 dir)
{   
    struct data_struct_s
    {
        uint32 stas_block_id  :8;
        uint32 dir            :1;
        uint32 resv           :23;
    };
    typedef struct data_struct_s data_struct_t; 
    uint16 start_idx        = block_id & 0xffff;
    uint8 ram_id            = (block_id >> 16) & 0x3;
    uint8 core_id           = (block_id >> 18) & 0x1;
    uint8 mcu_id            = 0;
    uint8 block_base_id     = 0;
    uint8 mac_group_id      = 0;
    data_struct_t send_data = {0x0};
    
    mac_group_id  = start_idx / SYS_AT_MCU_STATS_RAM_TBL_ENTRY_NUM_PER_MCMAC;    
    mcu_id        = core_id*AT_MCU_NUM_PER_CORE + ((ram_id == 2) ? (AT_MCU_NUM_PER_CORE - 1)  : mac_group_id);
    block_base_id = (ram_id == 1) ? 4 : 0;

    /* Send Sync Msg */
    send_data.stas_block_id = block_base_id + (start_idx % SYS_AT_MCU_STATS_RAM_TBL_ENTRY_NUM_PER_MCMAC) / SYS_AT_MCU_STATS_RAM_TBL_ENTRY_NUM_PER_BLOCK;
    send_data.dir           = (CTC_STATS_MAC_STATS_RX == dir) ? 0 : 1;
    CTC_ERROR_RETURN(sys_usw_dmps_msg_sync_send(lchip, mcu_id, SYS_DMPS_MSG_CODE_SYNC_C2M_CLEAR_MAC_STATS, sizeof(data_struct_t), &send_data, NULL)); 
    return CTC_E_NONE;
}

int32
sys_at_mcu_get_version(uint8 lchip, sys_usw_dmps_mcu_fw_version_t* p_mcu_version)
{   
    uint8  mcu_id       = 0;
    
    for (mcu_id = 0; mcu_id < AT_MCU_NUM_PER_CORE; mcu_id ++)
    {
        if (_sys_at_mcu_check_mcu_is_used(lchip, mcu_id))
        {
            break;
        }
    }

    /*Read MCU version */
    CTC_ERROR_RETURN(sys_at_mcu_read_shared_memory(lchip, mcu_id, GLB_INFO_VER_DATE,   0x0, &p_mcu_version->date));
    CTC_ERROR_RETURN(sys_at_mcu_read_shared_memory(lchip, mcu_id, GLB_INFO_VER_COMMIT, 0x0, &p_mcu_version->commit_id));

    return CTC_E_NONE;
}

uint8
sys_at_mcu_is_use_mac_id(uint8 lchip, uint16 mac_id)
{
    uint8 mcu_id                         = 0;
    uint8 core_id                        = 0;
    uint8 port_type                      = 0;
    uint8 mac_group_id                   = 0;
    sys_dmps_db_msg_mcu_info_t mcu_info = {0x0};
    sys_dmps_db_upt_info_t port_info = {0};

    CTC_ERROR_RETURN(sys_usw_dmps_db_upt_info_init(lchip, &port_info));
    DMPS_DB_SET_MAP_INFO(port_info,        DMPS_DB_MAC_ID,  mac_id);
    DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_MAC_GROUP_ID);
    DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_PORT_TYPE);
    DMPS_DB_SET_PROPERTY_UPDATE(port_info, DMPS_DB_CHAN_CORE_ID);
    CTC_ERROR_RETURN(sys_usw_dmps_db_get_port_info(lchip, &port_info));
    DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_MAC_GROUP_ID, mac_group_id);
    DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_PORT_TYPE,    port_type);
    DMPS_DB_GET_PROPERTY_INFO(port_info, DMPS_DB_CHAN_CORE_ID, core_id);

    if (!SYS_USW_IS_NETWORK_PORT(port_type))
    {
        return FALSE;
    }

    CTC_ERROR_RETURN(_sys_at_mcu_get_mcu_use_info(lchip, &mcu_info));

    if (SYS_DMPS_NETWORK_PORT == port_type) 
    {
        mcu_id = core_id*AT_MCU_NUM_PER_CORE + mac_group_id; 
    }
    else
    {
        mcu_id = core_id*AT_MCU_NUM_PER_CORE + (AT_MCU_NUM_PER_CORE - 1); 
    }

    if (CTC_BMP_ISSET(mcu_info.mcu_bmp, mcu_id))
    {
        return TRUE;
    }
    
    return FALSE;
}

int32
sys_at_mcu_show_debug_info(uint8 lchip, uint8 mcu_id)
{
    uint8* p_u8        = NULL;
    uint8  core_id     = 0;
    uint32 idx         = 0;
    uint32 inst_id     = SYS_AT_MCU_ID_PER_CORE(mcu_id);
    uint32 entry_id    = 0;
    uint32 cmd         = 0;
    uint32 index       = 0;
    uint32 stack_addr  = 0;
    uint32 stack_size  = 0;
    uint32 start_entry = 0;
    uint32 end_entry   = 0;
    uint32 free_bytes  = 0;
    uint32 m_mem[SYS_AT_MCUMEM_WORDS]  = {0x0};
        
    /* Get Core ID */
    SYS_AT_MCU_ID_TO_CORE_ID(core_id, mcu_id);
    
    CTC_ERROR_RETURN(sys_at_mcu_read_shared_memory(lchip, mcu_id, GLB_INFO_MAIN_THREAD_STACK_ADDR, 0x0, &stack_addr));
    CTC_ERROR_RETURN(sys_at_mcu_read_shared_memory(lchip, mcu_id, GLB_INFO_MAIN_THREAD_STACK_SIZE, 0x0, &stack_size));
    
    stack_addr = stack_addr & 0xFFFFF; 

    cmd = DRV_IOR(McuMem_t, DRV_ENTRY_FLAG);
    start_entry = stack_addr  / SYS_AT_MCUMEM_BYTES;
    end_entry   = start_entry + (stack_size / SYS_AT_MCUMEM_BYTES);
    p_u8 = (uint8*)m_mem;
    for (entry_id = start_entry; entry_id < end_entry; entry_id ++)
    {
        index       = DRV_INS(inst_id, entry_id);
        CTC_ERROR_RETURN(DMPS_DRV_IOCTL_CORE(lchip, index, core_id, cmd, m_mem));
        for (idx = (entry_id == start_entry ? (stack_addr%SYS_AT_MCUMEM_BYTES): 0); idx < SYS_AT_MCUMEM_BYTES; idx ++)
        {
            if (p_u8[idx] != '#')
            {
                break;
            }
            free_bytes ++;
        }

        if (idx < SYS_AT_MCUMEM_BYTES)
        {
            break;
        }
    }

    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "[Main Thread Info]\n");
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    Stack Addr : 0x%08x\n",   stack_addr);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    Stack Size : %u bytes\n", stack_size);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    Free  Size : %u bytes\n", free_bytes);
    SYS_MAC_DBG_OUT(CTC_DEBUG_LEVEL_DUMP, "    Use   Size : %u bytes\n", stack_size - free_bytes);

    CTC_ERROR_RETURN(sys_at_mcu_dump_db_info(lchip, mcu_id));

    return CTC_E_NONE;
}

